
#include "main.h"

//############################ LCD I/O DEFINE 

//lcd must be conected:     1) Data(4pins)to PORTx(Px,7-Px,4) or (Px,3-Px,0)
//    	    	  		    2) Control to PORTx(Px,2-Px,0)

#define PORT_OUT	  	   PORTD	  
#define PORT_INP	 	   PORTD
#define PORT_DIR	 	   TRISD
#define PORT_CONTR		PORTA
#define PORT_CONTR_DIR	TRISA

//#define	High_nibble     //if High_nibble ( Px,7 - Px,4 ) 
//if not define High_nibble, then--> (Px,3-Px,0)

/* #define lcd_ENA	   (1<<3) */
/* //RW=0-->write; RW=1-->read */
/* #define lcd_RW		   (1<<2) */
/* //RS=0--> command; RS=1--> data */
/* #define lcd_RS		   (1<<1) */

#define lcd_ENA	   (1<<5)
//RW=0-->write; RW=1-->read
#define lcd_RW		   (1<<4)
//RS=0--> command; RS=1--> data
#define lcd_RS		   (1<<3)

//the pin defining of "Data" (PORT_OUT)

#ifdef High_nibble
 #define	PIN_for_Data		   0x0F	 //if defining ( Px,7 - Px,4 ) 
 #define lcd_busy	   		   (1<<7)
#else
 #define	PIN_for_Data		   0xF0	 //if defining ( Px,3 - Px,0 )
 #define lcd_busy	   		   (1<<3)
#endif

#define	set_ENA()	   PORT_CONTR|=lcd_ENA 
#define	set_RW() 	   PORT_CONTR|=lcd_RW
#define	set_RS() 	   PORT_CONTR|=lcd_RS

#define	clr_ENA()		PORT_CONTR&=(~lcd_ENA)
#define	clr_RW() 	   PORT_CONTR&=(~lcd_RW)
#define	clr_RS() 	   PORT_CONTR&=(~lcd_RS)

#define	as_out() 	   PORT_DIR &= (PIN_for_Data)
#define	as_inp() 	   PORT_DIR |=~(PIN_for_Data)

static unsigned char lcd_line[4]={0x80, (0x80+0x40), (0x80+0x14), (0x80+0x54)};
unsigned char lcdNumber[10]; 
///////

unsigned char lcd_global =0;
unsigned char LCD_X, LCD_Y;

//void clock_ENA (void);
#define	clock_ENA()		{set_ENA(); NOP(); clr_ENA();}
//void delay (int k);
void lcd_ready (void);
void lcd_write_control (byte data);
void lcd_clear (void);
void lcd_goto(byte x, byte y);
void lcd_init(byte lcd_colums);
void lcd_putchar (byte data);
void lcd_putsf(const byte *string);
void lcd_puts (byte *string);
//void lcd_convert (unsigned int number);
//void lcd_printByte ( byte value);
//void lcd_convertZeroByte (byte number);
//void lcd_printZeroByte ( byte value);
void lcd_cursor( unsigned char sw );
void lcd_print_time( unsigned int Sec, unsigned char X, unsigned char Y );

void delay ( unsigned int cnt )
{
	while ( --cnt )
		NOP();
}

void lcd_ready (void)
{
	as_inp();
	set_RW();
	clr_RS();
	set_ENA();
	NOP();
	NOP();
	while ( (PORT_INP) & (lcd_busy) )
		continue;
	clr_ENA();
	clr_RW();
}

void lcd_write_control (unsigned char data)
{
	unsigned char temp_data;
	//PORT_CONTR_DIR|=lcd_ENA|lcd_RW|lcd_RS; 
	clr_RS();
	clr_RW();
	as_out();
	 
#ifdef   High_nibble
	PORT_OUT &= 0x0F; //the data bus clear 
	temp_data = data;
	temp_data &= 0xF0;
	PORT_OUT |= temp_data;
	clock_ENA();
	PORT_OUT &= 0x0F; //the data bus clear 
	temp_data = data; 
	temp_data << =4; 
	PORT_OUT |= temp_data;
	clock_ENA();
#else
	PORT_OUT &= 0xF0; //the data bus clear 
	temp_data = data;
	temp_data >>= 4;
	temp_data &= 0x0F;
	PORT_OUT |= temp_data;
	clock_ENA();
	PORT_OUT &= 0xF0; //the data bus clear 
	temp_data = data;
	temp_data &= 0x0F;
	PORT_OUT |= temp_data;
	clock_ENA();
#endif	 
}

/* #define LCD_STROBE_READ(value)	LCD_EN = 1; \ */
/* 				asm("nop"); asm("nop"); \ */
/* 				value=LCD_DATA_PORT; \ */
/* 				LCD_EN = 0;  */


/* #define LCD_STROBE_READ(value)	set_ENA(); \ */
/* 				asm("nop"); asm("nop"); \ */
/* 				value = PORT_INP; \ */
/* 				clr_ENA()  */


/* unsigned char lcd_read_char(unsigned char X, unsigned char Y) */
/* { */
/* 	unsigned char Char; */

/* 	lcd_goto(X,Y); */
/* 	delay(60); */
/* 	as_inp(); */
/* 	set_RW(); */
/* 	set_RS(); */
/* 	NOP(); */
/* 	NOP(); */

/* 	set_ENA(); */
/* 	NOP(); */
/* 	NOP(); */
/* 	Char = PORT_INP; */
/* 	clr_ENA(); */
/* 	Char <<= 4; */
	
/* 	set_ENA(); */
/* 	NOP(); */
/* 	NOP(); */
/* 	Char |= PORT_INP & 0x0F; */
/* 	clr_ENA(); */
	
/* 	as_out(); */
/* 	clr_RW(); */
/* 	clr_RS(); */
	
/* 	return Char; */
/* } */

unsigned char lcd_read_char(unsigned char X, unsigned char Y)
//unsigned char lcd_read_char()
{
	unsigned char Char;//, DDRAM_Address = 0x80;

	lcd_ready();
	lcd_write_control(lcd_line[Y]+X);
	delay(40);

	as_inp();
	set_RS();
	set_RW();
	NOP();
	NOP();

	set_ENA();
	NOP();
	NOP();
	Char = PORT_INP;
	clr_ENA();

	Char <<= 4;
	NOP();

	set_ENA();
	NOP();
	NOP();
	Char |= PORT_INP & 0x0F;
	clr_ENA();

//	as_out();
	
	return Char;
}

 
void lcd_read_line( unsigned char* Buffer, unsigned char StrNum )
{
	unsigned char i;

	//lcd_goto(0,StrNum);
	//delay(60);
	
	for( i = 0; i < 20; i++ )
	{
		Buffer[i] = lcd_read_char(i, StrNum); 
		//lcd_ready();
		//Buffer[i] = lcd_read_char(); 
	}

	Buffer[20] = '\n';
}

/* 21 characters for each line - [21] == '\n' */
void lcd_read_display( unsigned char* Buffer, unsigned char DisplayLine )
{
	unsigned char i;

	for( i = 0;  i < DisplayLine; i++ )
	{
		lcd_read_line(&Buffer[i*21], i);
	}

	i = 21*DisplayLine;
	Buffer[i++] = '\r';
	Buffer[i] = 0;
	lcd_goto(LCD_X, LCD_Y);
}

void lcd_clear (void)
{
	//lcd_ready();
	//lcd_write_control(0x0C);  
	//delay(10);
	lcd_ready();
	lcd_write_control(0x01);
	lcd_ready();
	lcd_write_control(lcd_line[0]+0);

	//delay(10);				////////
}	 

void lcd_goto(byte x, byte y)
{
	lcd_ready();
	LCD_X = x; LCD_Y = y;
	lcd_write_control(lcd_line[y]+x);
}	

void lcd_cursor( unsigned char sw )
{
	lcd_ready();
	lcd_write_control(sw);
}
	 
void lcd_init(byte lcd_colums)
{
	TRISA3 = 0;
	TRISA4 = 0;
	TRISA5 = 0;
	
 	delay(3000);
	lcd_line[2]=0x80+lcd_colums;
	lcd_line[3]=0xC0+lcd_colums;
	clr_ENA();
	clr_RS();
 	lcd_write_control(0x30);
	delay(3000);
	lcd_write_control(0x30);
	delay(3000);
	lcd_write_control(0x30);
	delay(3000);
	lcd_write_control(0x20);
	lcd_ready();
	lcd_write_control(0x28);
	//lcd_ready();
	//lcd_write_control(0x0F);  //cursor blink
	lcd_ready();
	lcd_write_control(0x0E);  //cursor  
	lcd_ready();
	lcd_write_control(0x06);  //cursor to right
	lcd_ready();
	lcd_write_control(0x80);  //Initialize DDRAM address to zero
	lcd_clear();
	//lcd_goto(0,0);
}	
	
void lcd_putchar (const byte data)
{
	byte temp_data;
	lcd_ready();
	//PORT_CONTR_DIR|=lcd_ENA|lcd_RW|lcd_RS; 
	set_RS();
	clr_RW();
	as_out();
#ifdef   High_nibble
	PORT_OUT&=0x0F; //the data bus clear 
	temp_data=data;
	temp_data&=0xF0;
	PORT_OUT|=temp_data;
	clock_ENA();
	PORT_OUT&=0x0F; //the data bus clear 
	temp_data=data; 
	temp_data<<=4; 
	temp_data&=0xF0;
	PORT_OUT|=temp_data;
	clock_ENA();
#else
	PORT_OUT&=0xF0; //the data bus clear 
	temp_data=data;
	temp_data>>=4;
	temp_data&=0x0F;
	PORT_OUT|=temp_data;
	clock_ENA();
	PORT_OUT&=0xF0; //the data bus clear 
	temp_data=data;
	temp_data&=0x0F;
	PORT_OUT|=temp_data;
	clock_ENA();
#endif
	
	LCD_X++;
}

void lcd_putsf(const byte *string)
{
	lcd_global = 0;
	while (*string)
	{	
		lcd_putchar(*string++);
		lcd_global++;
	}
}	

void lcd_puts (byte *string)
{
	//lcd_global = 0;
	while (*string)
	{
		//lcd_global++;
		lcd_putchar (*string++);
	}
	
}
 
void lcd_putds( byte *string, byte ByteCount )
{
	while(ByteCount--)
		lcd_putchar(*string++);
}

 
void ScrollMessage(unsigned char row, const char* Message)
{
	#define   TEMP_SIZE	21

	char TempS[TEMP_SIZE];
	static unsigned char  MHead = 0, p =0; //,Done=0;
	unsigned char count;
	static unsigned char i = 5;

	if( Time_10ms )
		--i;

	if ( i )
		return; 

	i = 100;

	TempS[TEMP_SIZE-1] = 0;

	if(row >2) row=1;

	lcd_cursor(OFF);
	p = MHead;
	for( count = 0; count < 20; count++ )
	{
		TempS[count] = Message[ p++ ];
		if ( TempS[count] == 0 )
		{
			TempS[count] = ' ';
			p = 0;
		}
	}

	MHead++; 
		if( Message[MHead] == 0 ) 
			MHead = 0 ;

	lcd_goto(0, row);
	lcd_puts(TempS);

}
 
void lcd_clear_str( unsigned char X, unsigned char Y )
{
	unsigned char i;
	lcd_goto( X, Y);
	for ( i = X; i < 20; i++ )
	{
		lcd_putchar(' '); 
	}
	lcd_goto( X, Y);
}
 


void lcd_print_Number ( unsigned long Number, unsigned char Aline ) 
{	  
	unsigned char Digit = 0, i, Begin = 0;

	if ( Aline == PASTE_ZERO_TIME )
		i = 0;
	else
		i = 8;

	while( 1)
	{
		while ( Number >= Exp[i] )
		{
			Number -= Exp[i];
			Digit++;
			Begin++;
		}

		if ( !Digit && !Begin  )
		{
			if (  Aline == RIGHT )
				lcd_putchar(' '); 
			else
				if ( Aline < LEFT )
					lcd_putchar('0');
		}
		else
			lcd_putchar(Digit+'0');

		Digit = 0;

		if ( i-- == 0 )
			break;
	}
	
	lcd_putchar( Number + '0');
}
 
typedef union
{
		unsigned int Long;
		struct 
		{	
				unsigned	b0	: 4;
				unsigned	b1	: 4;
				unsigned	b2	: 4;
				unsigned	b3	: 4;
				unsigned	b4	: 4;
				unsigned	b5	: 4;
				unsigned	b6	: 4;
				unsigned	b7	: 4;
	  	}Position;
		
}BCD_TYPE;

typedef union 
{
		unsigned long LONG;
		struct 
		{	
				unsigned char b0;
				unsigned char b1;
				unsigned char b2;
				unsigned LSB : 4;
				unsigned MSB : 4;		
		}BYTE;
		
}BCD_NUM;


void lcd_print_BCD( unsigned long BCD )
{
	unsigned char temp, i;
	BCD_NUM BCD_Num;
	
	BCD_Num.LONG = BCD;
	
	for ( i = 0; i < 8; i++ )
	{
		temp = BCD_Num.BYTE.MSB;
		if ( temp <= 9 ) 
		{
			lcd_putchar(temp + '0' );
		}
		BCD_Num.LONG <<= 4;
	}

}

void lcd_print_time( unsigned int Sec, unsigned char X, unsigned char Y )
{
	unsigned char Min, Seconds;
	
	Min = Sec / 60;
	Seconds = Sec % 60;
	lcd_clear_str (X, Y);
	lcd_print_Number(Min, PASTE_ZERO_TIME);
	lcd_putchar(':');
	lcd_print_Number(Seconds, PASTE_ZERO_TIME);
}

void lcd_print_str ( const unsigned char* Buffer, unsigned char X, unsigned char Y, unsigned char ClearDisplay )
{
	if ( ClearDisplay )
	{
		lcd_clear();
	}
	else
	{
		lcd_clear_str(0, Y);
	}

//	Ext_Display_Update();

	lcd_goto(X,Y);
	lcd_putsf(Buffer);
	lcd_global += X;

	//LCD_X = lcd_global;
	LCD_Y = Y;
} 
